package xhe.lib.base;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import org.yaml.snakeyaml.Yaml;

/**
 * <b> 工具类: </b> 解析yml文件类
 * 
 * @author xhe
 * @version V1.0.0.0
 * @version --2020年7月21日
 */
public class YmlUtils {
	// private static final Logger LOGGER = LogFactory.getLogger(YmlUtils.class);

	// private static String bootstrap_file = "classpath:application.yml";
	private static String bootstrap_file = "application.yml";

	private static Map<String, String> result = new HashMap<>();

	/**
	 * <b> 方法: </b> 根据文件路径获取yml的文件内容
	 * 
	 * @author xhe
	 * @param filePath 文件路径
	 * @param keys     第一个参数对应第一个key，第二个参数对应第二个key 比如spring.name下的所有
	 *                 就是两个参数、getYmlByFileName(bootstrap_file,"spring", "name");
	 * @return Map 对象集合
	 * @version V1.0.0.0
	 * @version --2020年7月21日
	 * @version --新增方法
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, String> getYmlByFileName(String filePath, String... keys) {
		result = new HashMap<>();
		if (filePath == null)
			filePath = bootstrap_file;

		InputStream oInputStream = null;
		try {

			ClassPathResource oResource = new ClassPathResource(filePath);

			oInputStream = oResource.getInputStream();

			Yaml oYaml = new Yaml();

			// 获取test.yaml文件中的配置数据，然后转换为obj
			Object oYamlFile = oYaml.loadAs(oInputStream, Map.class);

			Map<String, Object> oParams = (Map<String, Object>) oYamlFile;

			for (Map.Entry<String, Object> entry : oParams.entrySet()) {
				String key = entry.getKey();
				Object val = entry.getValue();

				if (keys.length != 0 && !keys[0].equals(key)) {
					continue;
				}
				if (val instanceof Map) {
					forEachYaml(key, (Map<String, Object>) val, 1, keys);
				} else {
					result.put(key, val.toString());
				}
			}

			return result;
		} catch (Exception e) {
			// LOGGER.error(e.getMessage(), e);
		} finally {
			if (oInputStream != null) {
				try {
					oInputStream.close();
				} catch (IOException e) {
					// LOGGER.error(e.getMessage(), e);
				}
			}
		}
		return null;
	}

	/**
	 * <b> 方法: </b> 根据文件路径获取yml的文件内容
	 * 
	 * @author xhe
	 * @param filePath 文件路径
	 * @param keys     第一个参数对应第一个key，第二个参数对应第二个key 比如spring.name下的所有
	 *                 就是两个参数、getYmlByFileName(bootstrap_file,"spring", "name");
	 * @return Map 对象集合
	 * @version V1.0.0.0
	 * @version --2020年7月21日
	 * @version --新增方法
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, String> getYmlMaps(String filePath, String... keys) {
		result = new HashMap<>();
		if (filePath == null)
			filePath = bootstrap_file;
		InputStream in = null;
		try {
			File file = ResourceUtils.getFile(filePath);
			in = new BufferedInputStream(new FileInputStream(file));
			Yaml props = new Yaml();
			Object obj = props.loadAs(in, Map.class);
			Map<String, Object> param = (Map<String, Object>) obj;

			for (Map.Entry<String, Object> entry : param.entrySet()) {
				String key = entry.getKey();
				Object val = entry.getValue();
				if (keys.length != 0 && !keys[0].equals(key)) {
					continue;
				}
				if (val instanceof Map) {
					forEachYaml(key, (Map<String, Object>) val, 1, keys);
				} else {
					result.put(key, val.toString());
				}
			}

			Map<String, String> oMapList = new HashMap<String, String>();

			if (!result.isEmpty()) {

				Set<Map.Entry<String, String>> entries = result.entrySet();

				for (Map.Entry<String, String> entry : entries) {
					String strKey = entry.getKey();
					String strValue = entry.getValue();

					for (String key : keys) {
						strKey = strKey.replace(key + ".", "");
					}

					oMapList.put(strKey, strValue);
				}

			}

			return oMapList;
		} catch (FileNotFoundException e) {
			// LOGGER.error(e.getMessage(), e);
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					// LOGGER.error(e.getMessage(), e);
				}
			}
		}
		return null;
	}

	/**
	 * <b> 方法: </b> getYmlMapsByFileName
	 * 
	 * @author xhe
	 * @param fileName 文件名称
	 * @param keys     第一个参数对应第一个key，第二个参数对应第二个key 比如spring.name下的所有
	 *                 就是两个参数、getYmlByFileName(bootstrap_file,"spring", "name");
	 * @return Map 对象集合
	 * @version V1.0.0.0
	 * @version --2020年7月21日
	 * @version --新增方法
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, String> getYmlMapsByFileName(String fileName, String... keys) {
		result = new HashMap<>();

		InputStream in = null;

		try {

			ClassPathResource resource = new ClassPathResource(fileName);
			// File sourceFile = resource.getFile();
			in = resource.getInputStream();

			Yaml props = new Yaml();
			// 获取test.yaml文件中的配置数据，然后转换为obj
			Object obj = props.loadAs(in, Map.class);

			Map<String, Object> param = (Map<String, Object>) obj;

			for (Map.Entry<String, Object> entry : param.entrySet()) {
				String key = entry.getKey();
				Object val = entry.getValue();
				if (keys.length != 0 && !keys[0].equals(key)) {
					continue;
				}
				if (val instanceof Map) {
					forEachYaml(key, (Map<String, Object>) val, 1, keys);
				} else {
					result.put(key, val.toString());
				}
			}

			Map<String, String> oMapList = new HashMap<String, String>();

			if (!result.isEmpty()) {

				Set<Map.Entry<String, String>> entries = result.entrySet();

				for (Map.Entry<String, String> entry : entries) {
					String strKey = entry.getKey();
					String strValue = entry.getValue();

					for (String key : keys) {
						strKey = strKey.replace(key + ".", "");
					}

					oMapList.put(strKey, strValue);
				}

			}

			return oMapList;
		} catch (Exception e) {
			// LOGGER.error(e.getMessage(), e);
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					// LOGGER.error(e.getMessage(), e);
				}
			}
		}
		return null;
	}

	/**
	 * <b> 方法: </b> getYmlMapsByFileName
	 * 
	 * @author xhe
	 * @param fileName 文件名称
	 * @param keys     第一个参数对应第一个key，第二个参数对应第二个key 比如spring.name下的所有
	 *                 就是两个参数、getYmlByFileName(bootstrap_file,"spring", "name");
	 * @return Map 对象集合
	 * @version V1.0.0.0
	 * @version --2020年7月21日
	 * @version --新增方法
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, Map<String, String>> getConnectionByYml() {

		String strFileName = "application.yml";
		String[] aryKeys = new String[] { "spring", "datasource" };

		result = new HashMap<>();

		InputStream oInputStream = null;

		try {

			ClassPathResource oResource = new ClassPathResource(strFileName);

			oInputStream = oResource.getInputStream();

			Yaml oYaml = new Yaml();

			// 获取test.yaml文件中的配置数据，然后转换为obj
			Object oYamlFile = oYaml.loadAs(oInputStream, Map.class);

			Map<String, Object> oParams = (Map<String, Object>) oYamlFile;

			for (Map.Entry<String, Object> oParam : oParams.entrySet()) {

				String strKey = oParam.getKey();
				Object oValue = oParam.getValue();

				if (aryKeys.length != 0 && !aryKeys[0].equals(strKey)) {
					continue;
				}
				if (oValue instanceof Map) {

					forEachYaml(strKey, (Map<String, Object>) oValue, 1, aryKeys);
				} else {

					result.put(strKey, oValue.toString());
				}
			}

			Map<String, Map<String, String>> oMapList = new HashMap<String, Map<String, String>>();

			if (!result.isEmpty()) {

				Set<Map.Entry<String, String>> oEntries = result.entrySet();

				for (Map.Entry<String, String> oEntry : oEntries) {

					String strKey = oEntry.getKey();
					String strValue = oEntry.getValue();
					String strFirstKey = "";
					String strSecondKey = "";

					for (String key : aryKeys) {
						strKey = strKey.replace(key + ".", "");
					}

					if (strKey.contains(".")) {
						strFirstKey = strKey.split("\\.")[0];
						strSecondKey = strKey.split("\\.")[1];
					} else {
						strFirstKey = "default";
						strSecondKey = strKey;
					}

					if (strSecondKey.equals("url")) {
						strSecondKey = "jdbc-url";
					}

					if (strValue.startsWith("ENC:")) {

						strValue = xhe.lib.io.Gzip.unGZip(xhe.lib.io.Gzip.uncompress(strValue.replace("ENC:", "")));

						// System.out.println(strKey + "_" + strSecondKey + ":" + strValue);
					}

					if (!oMapList.containsKey(strFirstKey)) {
						oMapList.put(strFirstKey, new HashMap<String, String>());
					}

					oMapList.get(strFirstKey).put(strSecondKey, strValue);
				}

			}

			return oMapList;

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (oInputStream != null) {
				try {
					oInputStream.close();
				} catch (IOException e) {
					// LOGGER.error(e.getMessage(), e);
				}
			}
		}
		return null;
	}

	/**
	 * <b> 方法: </b> 根据key获取值
	 * 
	 * @author xhe
	 * @param key yml文件的key
	 * @return String yml文件中key对应的value
	 * @throws FileNotFoundException 查找文件异常
	 * @version V1.0.0.0
	 * @version --2020年7月21日
	 * @version --新增方法
	 */
	public static String getValue(String key) throws FileNotFoundException {
		Map<String, String> map = getYmlByFileName(null);
		if (map == null)
			return null;
		return map.get(key);
	}

	/**
	 * <b> 方法: </b> 遍历yml文件，获取map集合
	 * 
	 * @author xhe
	 * @param key_str key
	 * @param obj     Map集合
	 * @param i       索引
	 * @param keys    keys
	 * @return
	 * @version V1.0.0.0
	 * @version --2020年7月21日
	 * @version --新增方法
	 */
	@SuppressWarnings("unchecked")
	private static Map<String, String> forEachYaml(String key_str, Map<String, Object> obj, int i, String... keys) {
		for (Map.Entry<String, Object> entry : obj.entrySet()) {
			String key = entry.getKey();
			Object val = entry.getValue();
			if (keys.length > i && !keys[i].equals(key)) {
				continue;
			}
			String str_new = "";
			if (!StringUtils.isEmpty(key_str)) {
				str_new = key_str + "." + key;
			} else {
				str_new = key;
			}
			if (val instanceof Map) {
				forEachYaml(str_new, (Map<String, Object>) val, ++i, keys);
				i--;
			} else {

				result.put(str_new, val.toString());
			}
		}

		return result;
	}

}
